package com.sc.nft.service.impl;

import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.SystemClock;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.*;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.meta.component.base.api.CommonResult;
import com.meta.user.client.api.UserLogOffRecordClient;
import com.meta.user.client.message.MetaUserInfoMessage;
import com.sc.nft.dao.*;
import com.sc.nft.dto.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.feign.HwCloudFeign;
import com.sc.nft.feign.ShuJuBaoCloudFeign;
import com.sc.nft.helper.MessageQueueHelper;
import com.sc.nft.helper.SandAccountHelper;
import com.sc.nft.mapper.UserReceiveInviteMapper;
import com.sc.nft.pool.SysMemberPool;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.Result;
import com.sc.nft.util.CheckAccountUtil;
import com.sc.nft.util.IdCardAuditUtil;
import com.sc.nft.vo.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 服务接口实现
 *
 * @author Sun
 * @description 由 Mybatisplus Code Generator 创建
 * @since 2022-05-29 10:36:55
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserInfoServiceImpl implements UserInfoService {

    private final UserInfoDao userInfoDao;

    private final StaticDataDao staticDataDao;

    private final SecondCollectionConfigDao secondCollectionConfigDao;

    private final IdcardInfoDao idcardInfoDao;

    private final InviteProductTaskDao inviteProductTaskDao;

    private final UserAssetsDao userAssetsDao;

    private final ProductStockDao productStockDao;

    private final HwCloudFeign hwCloudFeign;
    private final RedisTemplate redisTemplate;

    private final UserReceiveInviteMapper userReceiveInviteMapper;

    private final BlockChainTypeService blockChainTypeService;

    private final UserReceiveIntegralService userReceiveIntegralService;

    private final InviteTaskDao inviteTaskDao;

    private final PrivilegeDao privilegeDao;

    private final DigitalCollectionDao digitalCollectionDao;

    private final UserCollectionDao userCollectionDao;

    private final PrivilegeUseLogService privilegeUseLogService;

    private final UserWalletDao userWalletDao;

    private final UserRelevanceService userRelevanceService;

    private final UserChainInfoService userChainInfoService;

    private final UserCityServerCentreDao userCityServerCentreDao;
    private final UserWorkRoomDao userWorkRoomDao;
    private final ExitConsensusUserDao exitConsensusUserDao;

    private final UserBankCardDao userBankCardDao;

    private final SandWithdrawRecordDao sandWithdrawRecordDao;

    private final WithdrawBankCardDao withdrawBankCardDao;

    private final SandAccountHelper sandAccountHelper;

    private final SandBizRecordDao sandBizRecordDao;

    private Date exitTime = DateTime.of("2024-08-26 18:00:00", "yyyy-MM-dd HH:mm:ss");
    private final UserHnaExtDao userHnaExtDao;
    private final LlUserExtDao llUserExtDao;

    private final FilterIncomeListDao filterIncomeListDao;

    private final MessageQueueHelper messageQueueHelper;

    private final UserWalletDetailDao userWalletDetailDao;

    private final PayOrderDao payOrderDao;

    private final MallOrderDao mallOrderDao;

    private final MallOrderIncomeDao mallOrderIncomeDao;

    private final MallPayOrderRecordDao mallPayOrderRecordDao;

    private final UserLogOffRecordClient userLogOffRecordClient;
    private final UserMarketValueDao userMarketValueDao;

    private final UserEquityPropsDao userEquityPropsDao;
    private final UserChainInfoDao userChainInfoDao;
    private final UserEcologyPointsDao userEcologyPointsDao;

    private final ShuJuBaoCloudFeign shuJuBaoCloudFeign;
    private final FaceCheckRecordDao faceCheckRecordDao;


    @Override
    public void initUserChain() {
        // 获取所有用户数据
        QueryWrapper<UserInfo> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("bind_flag", true);
        List<UserInfo> list = userInfoDao.list(objectQueryWrapper);
        for (UserInfo userInfo : list) {
            List<Long> data = new ArrayList<>();
            initUserChains(userInfo, data);
            Collections.reverse(data);
            String chain = "";
            for (Long aLong : data) {
                chain = StrUtil.format("{}{},", chain, aLong);
            }

            userInfoDao.updateRecommendUserIdList(userInfo.getId(), StrUtil.isEmpty(chain) ? chain : chain.substring(0, chain.length() - 1));
        }
    }

    public void initUserChains(UserInfo userInfo, List<Long> data) {
        // 死循环查询每一个用户的上级,查到空为止.
        Long recommendUserId = userInfo.getRecommendUserId();
        while (true) {
            UserInfo byId = userInfoDao.getById(recommendUserId);
            if (BeanUtil.isEmpty(byId)) {
                break;
            }
            data.add(byId.getId());
            recommendUserId = byId.getRecommendUserId();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserLoginVO registeUser(String inviteCode, Integer types, String userAccount, String pwd) {

        UserInfo accountUser;

        if (!CheckAccountUtil.checkPhone(userAccount)) {
            throw new GlobalRunTimeException(ErrorCode.INCORRECT_ACCOUNT_FORMAT);
        }
        accountUser = userInfoDao.getOneByUserTel(userAccount);

        if (ObjectUtil.isNotEmpty(accountUser)) {
            throw new GlobalRunTimeException(ErrorCode.ACCOUNT_EXIST);
        }

        CommonResult<Boolean> logOffKeyExists = userLogOffRecordClient.logOffKeyExists(userAccount);
        if (BooleanUtil.isTrue(logOffKeyExists.getData())) {
            throw new GlobalRunTimeException("距离上次注销不满3个月，禁止注册！");
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setUserTel(userAccount);
        //信息脱敏
        userInfo.setNickName(DesensitizedUtil.mobilePhone(userAccount));
        userInfo.setPwd(CheckAccountUtil.pwdToMd5(pwd));
        userInfo.setRecommendUserId(1L);
        userInfo.setHoldToken(BigDecimal.ZERO);
        userInfo.setIsFreeze(Boolean.FALSE);
        userInfo.setIsSm(Boolean.FALSE);
        userInfo.setIsCreator(Boolean.FALSE);
        userInfo.setIsAddr(Boolean.FALSE);
        userInfo.setIsUser(UserAccoutTypeEnum.USER_TEL.getCode());
        userInfo.setIsValid(Boolean.FALSE);
        userInfo.setIsThird(Boolean.TRUE);
        userInfo.setOutSideKey(Long.toHexString(SystemClock.now() / 10) + RandomUtil.randomInt(000, 999));
        long snowflakeNextId = IdUtil.getSnowflakeNextId();
        userInfo.setUserUuid(String.valueOf(snowflakeNextId));
        userInfo.setSandWithdrawUuid(String.valueOf(snowflakeNextId));

        StaticData avatarImgStaticData = staticDataDao.getByType("default_avatar_img");
        userInfo.setAvatarImg(avatarImgStaticData.getValue());
        userInfo.setBindFlag(false);
        StaticData backGroundImgStaticData = staticDataDao.getByType("default_back_ground_img");
        userInfo.setBackGroundImg(backGroundImgStaticData.getValue());

        // 插入
        userInfoDao.saveWithSync(userInfo);
        Long userId = userInfo.getId();

//        if (StrUtil.isNotBlank(inviteCode)) {
//            invite(userInfo, inviteCode);
//        }

        UserLoginVO userLoginVO = new UserLoginVO();
        userLoginVO.setUuid(userInfo.getUserUuid());
        userLoginVO.setToken(userLogin(userId));
        userLoginVO.setUserId(userId);

        // 注册后置处理 初始化钱包和地址
        messageQueueHelper.sendMessage(MessageTopic.USER_REGISTER_INIT, userInfo);
        return userLoginVO;
    }

    @Override
    public void initUserWalletAndAddr(UserInfo userInfo) {
        //初始化积分账户
        blockChainTypeService.insertUserAssets(userInfo.getId());

        UserWallet wallet = userWalletDao.getByUserId(userInfo.getId());
        if (ObjectUtil.isNull(wallet)) {
            //初始化钱包
            UserWallet userWallet = new UserWallet();
            userWallet.setUserId(userInfo.getId());
            userWallet.setSumIncome(BigDecimal.ZERO);
            userWallet.setBalance(BigDecimal.ZERO);
            userWallet.setWithdrawingAmount(BigDecimal.ZERO);
            userWallet.setTransferAmount(BigDecimal.ZERO);
            userWallet.setSumWithdraw(BigDecimal.ZERO);
            userWallet.insert();
        }

        UserEcologyPoints userEcology = userEcologyPointsDao.getOneByUserId(userInfo.getId());
        if (ObjectUtil.isNull(userEcology)) {
            UserEcologyPoints userEcologyPoints = new UserEcologyPoints();
            userEcologyPoints.setUserId(userInfo.getId());
            userEcologyPoints.setAmount(BigDecimal.ZERO);
            userEcologyPoints.setSumIncomeAmount(BigDecimal.ZERO);
            userEcologyPoints.setSumExpendAmount(BigDecimal.ZERO);
            userEcologyPoints.insert();
        }


        UserChainInfo userChain = userChainInfoDao.getByUserId(userInfo.getId());
        if (ObjectUtil.isNull(userChain)) {
            UserChainInfo userChainInfo = new UserChainInfo();
            userChainInfo.setUserId(userInfo.getId());
            userChainInfo.setUserUuid(userInfo.getUserUuid());
            userChainInfo.setUserKey(SecureUtil.md5(userChainInfo.getUserUuid()));
            userChainInfo.setStatus(false);
            userChainInfo.insert();

            //同步注册上链
            userChainInfoService.userRegister(userChainInfo);
        }
        UserConsensus userConsensus = new UserConsensus();
        userConsensus.setUserId(userInfo.getId());
        userConsensus.setInitSmeltSet(0);
        userConsensus.setConsensusNum(BigDecimal.ZERO);
        userConsensus.setSmeltOutRatio(BigDecimal.ONE);
        userConsensus.insert();

    }

    @Override
    public UserLoginVO marketValueAccountRegistration(String inviteCode, Integer types, String userAccount, String pwd) {
        UserInfo userInfo = new UserInfo();
        userInfo.setUserTel(userAccount);
        //信息脱敏
        userInfo.setNickName(DesensitizedUtil.mobilePhone(userAccount));
        userInfo.setPwd(CheckAccountUtil.pwdToMd5(pwd));
        userInfo.setRecommendUserId(1L);
        userInfo.setHoldToken(BigDecimal.ZERO);
        userInfo.setIsFreeze(Boolean.FALSE);
        userInfo.setIsSm(Boolean.FALSE);
        userInfo.setIsCreator(Boolean.FALSE);
        userInfo.setIsAddr(Boolean.FALSE);
        userInfo.setIsUser(UserAccoutTypeEnum.USER_TEL.getCode());
        userInfo.setIsValid(Boolean.FALSE);
        userInfo.setIsThird(Boolean.TRUE);
        // 密码00000
        userInfo.setTransactionPassword("8AD9902AECBA32E2");
        userInfo.setOutSideKey(Long.toHexString(SystemClock.now() / 10) + RandomUtil.randomInt(000, 999));
        long snowflakeNextId = IdUtil.getSnowflakeNextId();
        userInfo.setUserUuid(String.valueOf(snowflakeNextId));
        userInfo.setSandWithdrawUuid(String.valueOf(snowflakeNextId));

        StaticData avatarImgStaticData = staticDataDao.getByType("default_avatar_img");
        userInfo.setAvatarImg(avatarImgStaticData.getValue());
        userInfo.setBindFlag(false);
        StaticData backGroundImgStaticData = staticDataDao.getByType("default_back_ground_img");
        userInfo.setBackGroundImg(backGroundImgStaticData.getValue());

        //插入
//        userInfo.insert();
        userInfoDao.saveWithSync(userInfo);
        Long userId = userInfo.getId();

//        if (StrUtil.isNotBlank(inviteCode)) {
//            invite(userInfo, inviteCode);
//        }

        UserLoginVO userLoginVO = new UserLoginVO();
        userLoginVO.setUuid(userInfo.getUserUuid());
        userLoginVO.setToken(userLogin(userId));
        userLoginVO.setUserId(userId);

        //初始化积分账户
        blockChainTypeService.insertUserAssets(userId);


        //初始化钱包
        UserWallet userWallet = new UserWallet();
        userWallet.setUserId(userId);
        userWallet.setSumIncome(BigDecimal.ZERO);
        userWallet.setBalance(BigDecimal.ZERO);
        userWallet.setWithdrawingAmount(BigDecimal.ZERO);
        userWallet.setTransferAmount(BigDecimal.ZERO);
        userWallet.setSumWithdraw(BigDecimal.ZERO);
        userWallet.insert();

        UserChainInfo userChainInfo = new UserChainInfo();
        userChainInfo.setUserId(userId);
        userChainInfo.setUserUuid(userInfo.getUserUuid());
        userChainInfo.setUserKey(SecureUtil.md5(userChainInfo.getUserUuid()));
        userChainInfo.setStatus(false);
        userChainInfo.insert();

        UserEcologyPoints userEcologyPoints = new UserEcologyPoints();
        userEcologyPoints.setUserId(userId);
        userEcologyPoints.setAmount(BigDecimal.ZERO);
        userEcologyPoints.setSumIncomeAmount(BigDecimal.ZERO);
        userEcologyPoints.setSumExpendAmount(BigDecimal.ZERO);
        userEcologyPoints.insert();

        //同步注册上链
        userChainInfoService.userRegister(userChainInfo);

        return userLoginVO;
    }

    @Override
    public MapAccumulationVO mapAccumulation(UserInfo user) {
        BigDecimal earnings = mallOrderIncomeDao.mapAccumulation(user.getId());
        MapAccumulationVO result = new MapAccumulationVO();
        result.setEarnings(earnings);
        return result;
    }

    @Override
    public IPage<MapAccumulationDetailsVO> mapAccumulationDetails(Page page, UserInfo user) {
        return mallOrderIncomeDao.mapAccumulationDetails(page, user.getId());
    }

    @Override
    public UserInfo getById(Long userId) {
        return userInfoDao.getById(userId);
    }

    @Override
    public UserInfoVO getUserInfoById(Long userId) {
        UserInfo userInfo = userInfoDao.getById(userId);
        IdcardInfo idcardInfo = idcardInfoDao.findLastOneByUserIdAndIsPass(userId);
        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setUserId(userId);
        userInfoVO.setUserTel(userInfo.getUserTel());
        userInfoVO.setIsSm(userInfo.getIsSm());
        if(idcardInfo != null){
            userInfoVO.setCardId(idcardInfo.getCardId());
        }
        return userInfoVO;
    }

    /**
     * 根据idList获取用户信息
     *
     * @param userIdList
     * @return
     */
    @Override
    public List<UserInfo> getByIdList(List<Long> userIdList) {
        return userInfoDao.getByIdList(userIdList);
    }

    @Override
    public Map<Long, UserInfo> getByIdListToMap(List<Long> userIdList) {
        if (CollectionUtils.isEmpty(userIdList)) {
            return new HashMap<>();
        }
        List<UserInfo> userInfoList = userInfoDao.getByIdList(userIdList);
        return userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, x -> x));
    }

    @Override
    public void syncRegister(MetaUserInfoMessage message) {
        // 创建用户
        UserInfo userInfo = new UserInfo();
        // 同步字段
        userInfo.setId(message.getId());    // ID系同步数值，不能使用自增
        userInfo.setUserTel(message.getUserTel());
        userInfo.setNickName(message.getNickName());
        userInfo.setPwd(message.getPwd());
        userInfo.setRecommendUserId(null == message.getRecommendUserId() ? 1L : message.getRecommendUserId());
        userInfo.setUserUuid(message.getUserUuid());
        userInfo.setInviteCode(message.getInviteCode());
        // 默认字段
        userInfo.setHoldToken(BigDecimal.ZERO);
        userInfo.setIsFreeze(Boolean.FALSE);
        userInfo.setIsSm(Boolean.FALSE);
        userInfo.setIsCreator(Boolean.FALSE);
        userInfo.setIsAddr(Boolean.FALSE);
        userInfo.setIsUser(UserAccoutTypeEnum.USER_TEL.getCode());
        userInfo.setIsValid(Boolean.FALSE);
        userInfo.setIsThird(Boolean.TRUE);
        userInfo.setOutSideKey(Long.toHexString(SystemClock.now() / 10) + RandomUtil.randomInt(0, 999));
        userInfo.setSandWithdrawUuid(userInfo.getUserUuid());
        userInfo.setBindFlag(StrUtil.isBlank(userInfo.getInviteCode()) ? Boolean.FALSE : Boolean.TRUE);
        StaticData avatarImgStaticData = staticDataDao.getByType("default_avatar_img");
        userInfo.setAvatarImg(avatarImgStaticData.getValue());
        StaticData backGroundImgStaticData = staticDataDao.getByType("default_back_ground_img");
        userInfo.setBackGroundImg(backGroundImgStaticData.getValue());
        Boolean result = userInfoDao.saveForSyncConsumer(userInfo);
        if (!result) {
            throw new GlobalRunTimeException(ErrorCode.SYS_ERROR);
        }

        // 邀请
        if (StrUtil.isNotBlank(userInfo.getInviteCode())) {
            syncInvite(message);
        }

        // 注册后置处理 初始化钱包和地址
        messageQueueHelper.sendMessage(MessageTopic.USER_REGISTER_INIT, userInfo);
    }


    /**
     * 获取所有下级
     *
     * @param userId
     * @return
     */
    @Override
    public List<Long> listRecommendByUserId(Long userId) {
        return userInfoDao.listRecommendByUserId(userId);
    }

    /**
     * 获取所有下级
     *
     * @param userIdList@return
     */
    @Override
    public List<UserRecommendDTO> listRecommendByUserIdList(List<Long> userIdList) {
        return userInfoDao.listRecommendByUserIdList(userIdList);
    }

    /**
     * 用户中心同步专用 与上方的syncRegister配合
     *
     * @param message
     */
    private void syncInvite(MetaUserInfoMessage message) {
        if (message.getRecommendUserId() == null) {
            return;
        }

        // 推荐人信息
        UserInfo recommendUserInfo = userInfoDao.getById(message.getRecommendUserId());
        if (Objects.isNull(recommendUserInfo)) {
            return;
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setId(message.getId());
        userInfo.setInviteCode(message.getInviteCode());
        userInfo.setBindFlag(message.getBindFlag());
        userInfo.setRecommendUserId(message.getRecommendUserId());

        // 初始化用户邀请关系
        String recommendUserIdList = recommendUserInfo.getRecommendUserIdList();
        if (recommendUserIdList.equals("0") || StrUtil.isBlank(recommendUserIdList)) {
            userInfo.setRecommendUserIdList(recommendUserInfo.getId().toString());
        } else {
            userInfo.setRecommendUserIdList(recommendUserIdList + "," + recommendUserInfo.getId());
        }
        userInfoDao.updateForSyncConsumer(userInfo);

        // 注册的时候,一起生成树状的对应图标
        userRelevanceService.userInfoDataSynchronism(userInfo.getRecommendUserIdList(), userInfo.getUserTel(), userInfo.getId());
        messageQueueHelper.sendMessage(MessageTopic.USER_REGISTER, recommendUserInfo);
    }


    @Override
    public UserInviteVO getUserInvitePage() {

        UserInfo user = UserPool.getUser();

        //实名邀请数量
        Integer validInviteNum = user.getThirdSmNum();
        //成功邀请数量
        Integer realValidInviteNum = user.getThirdValidNum();
        UserInviteVO userInviteVO = BeanUtil.toBean(user, UserInviteVO.class);
        userInviteVO.setRealNum(validInviteNum);
        userInviteVO.setValidInviteNum(realValidInviteNum);
        userInviteVO.setInviteNum(user.getThirdInviteNum());
        //二维码邀请链接
        StaticData staticData = staticDataDao.getByType("share_url");
        userInviteVO.setShareUrl(staticData.getValue() + user.getInviteCode());

        List<InviteTask> list = inviteTaskDao.selectAll();
        ArrayList<InviteTaskVO> inviteTaskVOList = new ArrayList<>();
        //查询记录表

        List<Long> ids = userReceiveInviteMapper.findInviteTaskIdListByUserId(user.getId());
        for (InviteTask inviteTask : list) {
            InviteTaskVO inviteTaskVO = BeanUtil.toBean(inviteTask, InviteTaskVO.class);
            inviteTaskVO.setInviteId(inviteTask.getId());
            inviteTaskVO.setValidInviteNum(realValidInviteNum);
            //奖励名称
            inviteTaskVO.setAwardName(inviteTask.getInvitateRewardName());

            if (ids.contains(inviteTask.getId())) {
                inviteTaskVO.setTypeName("已发放");
            } else if (realValidInviteNum >= inviteTask.getInviteNum()) {
                inviteTaskVO.setTypeName("未发放");
            } else {
                inviteTaskVO.setTypeName("未达标");
                List<InviteProductTask> inviteProductTaskList = inviteProductTaskDao.getListByInviteTaskId(inviteTask.getId());
                for (InviteProductTask inviteProductTask : inviteProductTaskList) {
                    Integer usableStockCount = productStockDao.getUsableStockCount(inviteProductTask.getProductId());
                    if (usableStockCount <= 0) {
                        inviteTaskVO.setTypeName("已结束");
                    }
                }
            }

            inviteTaskVOList.add(inviteTaskVO);
        }
        userInviteVO.setList(inviteTaskVOList);

        if (list.size() == 0) {
            userInviteVO.setMsg("第三轮邀请活动已结束，敬请期待");
        }
        String inviteTaskUrl = staticDataDao.getByType("invite_task_url").getValue();
        userInviteVO.setInviteTaskUrl(inviteTaskUrl);
        String invertStepUrl = staticDataDao.getByType("invert_step_url").getValue();
        userInviteVO.setInvertStepUrl(invertStepUrl);
        return userInviteVO;
    }

    @Override
    public List<HashMap> findPositionRanking() {
        return userInfoDao.findPositionRanking();
    }

    @Override
    public HashMap findPositionRankingById(Long id) {
        return userInfoDao.findPositionRankingById(id);
    }

    @Override
    public List<HashMap> findInviteRanking() {
        return userInfoDao.findInviteRanking();
    }

    @Override
    public HashMap findInviteRankingById(Long id) {
        return userInfoDao.findInviteRankingById(id);
    }

    @Override
    public ArrayList<UserInviteDetails> getInviteDetails() {
        UserInfo user = UserPool.getUser();

        List<UserInfo> list = userInfoDao.getListByRecommendUserId(user.getId());

        ArrayList<UserInviteDetails> userInviteDetailList = new ArrayList<>();
        for (UserInfo info : list) {
            Boolean isSm = info.getIsSm();
            Boolean isValid = info.getIsValid();
            UserInviteDetails userInviteDetails = new UserInviteDetails();
            userInviteDetails.setIsSm(isSm);
            userInviteDetails.setIsValid(isValid);
            userInviteDetails.setIsInvertBuy(isValid);

            if (isSm && isValid) {
                userInviteDetails.setIsValidInvite(Boolean.TRUE);
            } else {
                userInviteDetails.setIsValidInvite(Boolean.FALSE);
            }
            userInviteDetails.setIsThird(info.getIsThird());
            userInviteDetails.setUserUuId(info.getUserUuid());
            userInviteDetailList.add(userInviteDetails);
        }
        return userInviteDetailList;
    }

    @Override
    public UserDetailVO getUserDetail(Long id) {
        UserDetailVO result = new UserDetailVO();
        UserInfo userInfo = userInfoDao.getById(id);
        if (ObjectUtil.isNull(userInfo)) {
            throw new GlobalRunTimeException("用户不存在");
        }
        //上级用户id
        UserInfo recommendUser = userInfoDao.getById(userInfo.getRecommendUserId());
        if (ObjectUtil.isNotNull(recommendUser)) {
            result.setUserTel(recommendUser.getUserTel());
        }
        //最近的服务中心
        Long cityServiceCenterUserId = userCityServerCentreDao.accessTheNearestCityServiceCenter(id);
        if (ObjectUtil.isNotNull(cityServiceCenterUserId)) {
            UserInfo serverCenterUser = userInfoDao.getById(cityServiceCenterUserId);
            if (ObjectUtil.isNotNull(serverCenterUser)) {
                result.setServerCenterTel(serverCenterUser.getUserTel());
            }
        }
        //最近的社区网点
        Long workRoomUserId = userWorkRoomDao.accessTheNearestCityServiceCenter(id);
        if (ObjectUtil.isNotNull(workRoomUserId)) {
            UserInfo workRoomUser = userInfoDao.getById(workRoomUserId);
            if (ObjectUtil.isNotNull(workRoomUser)) {
                result.setWorkRoomTel(workRoomUser.getUserTel());
            }
        }
        return result;
    }

    @Override
    public UserPageVO getUserPage() {
        UserInfo user = UserPool.getUser();
        UserPageVO userPageVO = BeanUtil.toBean(user, UserPageVO.class);
        userPageVO.setUserId(user.getId());
        userPageVO.setRegisterTime(user.getCreateTime());
        ExitConsensusUser exitConsensusUser = exitConsensusUserDao.getByUserId(user.getId());
        if (user.getCreateTime().after(exitTime)) {
            userPageVO.setAllowExitConsensus(false);
        } else {
            userPageVO.setAllowExitConsensus(ObjectUtil.isNull(exitConsensusUser) || exitConsensusUser.getStatus());
        }
        userPageVO.setIsConsensusUser(ObjectUtil.isNotNull(exitConsensusUser) && exitConsensusUser.getStatus());
        UserAssets userAssets = userAssetsDao.getByUserIdAndCoinId(user.getId(), CoinCategoryEnum.INTEGRAL.getCode());
        UserChainInfo userChainInfo = userChainInfoService.getByUserId(user.getId());
        if (ObjectUtil.isNull(userChainInfo)) {
            userPageVO.setChainAddr("生成中");
        } else {
            userPageVO.setChainAddr(userChainInfo.getAddress());
        }
        userPageVO.setUserUuid(userPageVO.getChainAddr());
        if (ObjectUtil.isEmpty(userAssets)) {
            userPageVO.setIntegralNum(BigDecimal.ZERO);
        } else {
            userPageVO.setIntegralNum(userAssets.getTokenNum());
        }

        //二维码邀请链接
        StaticData staticData = staticDataDao.getByType("share_url");
        userPageVO.setShareUrl(staticData.getValue() + user.getInviteCode());
        //区块链链浏览器
        String tianheChainBrowser = staticDataDao.getByType("tianhe_chain_browser").getValue();
        userPageVO.setTianheChainBrowser(tianheChainBrowser);
        Integer userFans = userRelevanceService.getUserFans();
        userPageVO.setFans(userFans);
        userPageVO.setSubscribe(1);
        StaticData openShop = staticDataDao.getByType("scroll_shop_collection_id");
        userPageVO.setOpenScrollShop(false);
        if (ObjectUtil.isNotNull(openShop) && ObjectUtil.isNotNull(openShop.getValue())) {
            if (userCollectionDao.getCountByCollectionIdAndUserId(Long.parseLong(openShop.getValue()), user.getId()) > 0) {
                userPageVO.setOpenScrollShop(true);
            }
        }
        return userPageVO;
    }

    @Override
    public ProfitVO getProfit(UserInfo userInfo) {
        ProfitVO profitVO = new ProfitVO();
        BigDecimal setSumWithdrawalAmount = userWalletDetailDao.historicalWithdrawal(userInfo.getId());
        BigDecimal rechargeAmount = userWalletDetailDao.rechargeAmount(userInfo.getId());
        BigDecimal payAmount = payOrderDao.getPayAmount(userInfo.getId());
        BigDecimal mallPayAmount = mallPayOrderRecordDao.getPayAmount(userInfo.getId());
        BigDecimal payAmountAndMallPayAmount = payAmount.add(mallPayAmount);
        profitVO.setSumWithdrawalAmount(setSumWithdrawalAmount.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        profitVO.setSumRechargeAmount(rechargeAmount.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        profitVO.setCardPaymentAmount(payAmountAndMallPayAmount.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        PositionStatisticalVO positionStatisticalVO = digitalCollectionDao.positionStatistical();
        UserWallet userWallet = userWalletDao.getByUserId(userInfo.getId());
        BigDecimal wallet = userWallet.getBalance().add(userWallet.getPayBalance()).add(userWallet.getWishBalance());
        profitVO.setWallet(userWallet.getBalance().setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        profitVO.setRedEnvelope(userWallet.getPayBalance().setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        profitVO.setWishBalance(userWallet.getWishBalance().setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        BigDecimal ipMallValue = mallOrderDao.getUserTotalPrice(userInfo.getId());
        BigDecimal ipMallRefundValue = mallOrderDao.getUserRefundPrice(userInfo.getId());
        profitVO.setIpMallValue(ipMallValue.subtract(ipMallRefundValue).setScale(2, BigDecimal.ROUND_DOWN).toPlainString());

        // 持仓市值
        BigDecimal currentAssets = BigDecimal.ZERO;
        if (!BeanUtil.isEmpty(positionStatisticalVO)) {
            if (!StrUtil.isEmpty(positionStatisticalVO.getPositionMarketValue())) {
                currentAssets = Convert.toBigDecimal(positionStatisticalVO.getPositionMarketValue());
            }
        }
        BigDecimal userSmeltCost = userMarketValueDao.getUserSmeltCost(userInfo.getId());
        profitVO.setEcologicalSmeltingCost(userSmeltCost.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        profitVO.setIpMallWaitingIncome(mallOrderIncomeDao.getSumWaitingIncomeByUserId(userInfo.getId()).setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        profitVO.setCurrentAssets(currentAssets.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        profitVO.setProfit(setSumWithdrawalAmount.add(wallet).add(currentAssets).add(ipMallValue).
                add(userSmeltCost).subtract(rechargeAmount).subtract(payAmountAndMallPayAmount).setScale(2, BigDecimal.ROUND_DOWN).toPlainString());

        return profitVO;
    }

    @Override
    public GetCertificationTypeVO getCertificationType() {
        UserInfo user = UserPool.getUser();
        Boolean isSm = user.getIsSm();
        GetCertificationTypeVO getCertificationTypeVO = new GetCertificationTypeVO();


        if (isSm) {
            IdcardInfo idcardInfo = idcardInfoDao.findLastOneByUserIdAndIsPass(user.getId());
            getCertificationTypeVO.setIsPass(1);
            getCertificationTypeVO.setName(idcardInfo.getName());
            getCertificationTypeVO.setCardId(idcardInfo.getCardId());
        } else {
            List<IdcardInfo> listByUserIdAndIsPass = idcardInfoDao.findListByUserIdAndIsPass(user.getId(), IdCardIsPassTypeEnum.UNDER_REVIEW.getCode());
            if (listByUserIdAndIsPass.size() > 0) {
                getCertificationTypeVO.setIsPass(IdCardIsPassTypeEnum.UNDER_REVIEW.getCode());
            }
            IdcardInfo idcardInfo = idcardInfoDao.findLastOneByUserId(user.getId());
            if (ObjectUtil.isEmpty(idcardInfo)) {
                getCertificationTypeVO.setIsPass(IdCardIsPassTypeEnum.NO_APPLY.getCode());
            } else {
                getCertificationTypeVO.setIsPass(idcardInfo.getIsPass());
                getCertificationTypeVO.setName(idcardInfo.getName());
                getCertificationTypeVO.setCardId(idcardInfo.getCardId());
            }
            List<FaceCheckRecord> newByUserList = faceCheckRecordDao.getNewByUserId(user.getId());
            if (!CollectionUtils.isEmpty(newByUserList)) {
                if (newByUserList.get(0).getCheckStatus() == 1) {
                    getCertificationTypeVO.setFaceFail(Boolean.TRUE);
                }
            }
        }

        Integer isUser = user.getIsUser();
        if (isUser == UserAccoutTypeEnum.USER_TEL.getCode()) {
            getCertificationTypeVO.setUserAccount("当前手机号: " + user.getUserTel());
        } else {
            getCertificationTypeVO.setUserAccount("当前邮箱号: " + user.getUserEmail());
        }
        String faceIsClose = staticDataDao.getByType("face_is_close").getValue();

        if (StrUtil.isBlank(faceIsClose)) {
            getCertificationTypeVO.setFaceIsClose(Boolean.TRUE);
        } else if ("0".equals(faceIsClose)) {
            getCertificationTypeVO.setFaceIsClose(Boolean.FALSE);
        } else {
            getCertificationTypeVO.setFaceIsClose(Boolean.TRUE);
        }
        if (getCertificationTypeVO.getFaceIsClose() && IdCardIsPassTypeEnum.UNDER_REVIEW.getCode().equals(getCertificationTypeVO.getIsPass())) {
            List<FaceCheckRecord> newByUserId = faceCheckRecordDao.getNewByUserId(user.getId());
            if (CollectionUtils.isEmpty(newByUserId) || newByUserId.get(0).getCheckStatus() != 0) {
                FaceCheckRecord faceCheckRecord = new FaceCheckRecord();
                faceCheckRecord.setUserId(user.getId());
                faceCheckRecord.setCheckStatus(0);
                faceCheckRecord.insert();
            }
            IdRequest idRequest = new IdRequest();
            idRequest.setId(user.getId());
            String faceCheckUrl = shuJuBaoCloudFeign.liveDetection(idRequest);
            if (StringUtils.isEmpty(faceCheckUrl)) {
                throw new GlobalRunTimeException("系统繁忙,请稍后重试");
            }
            getCertificationTypeVO.setFaceCheckUrl(faceCheckUrl);
        }
        getCertificationTypeVO.setUserTel(user.getUserTel());
        getCertificationTypeVO.setNickName(user.getNickName());
        getCertificationTypeVO.setHeadUrl(user.getAvatarImg());
        return getCertificationTypeVO;
    }

    @Override
    public Page<UserManageVO> pageUserInfo(String userUuid, String nickName, String userTel, Date startDate, Date endDate, String address, int pageNo, int pageSize) {
        return userInfoDao.pageUserInfo(userUuid, nickName, userTel, startDate, endDate, address, pageNo, pageSize);
    }

    @Override
    public Page<UserEquityPropsSimpleVO> userWithEquityProps(Long userId, String firstTitle, int pageNo, int pageSize) {
        return userEquityPropsDao.pageUserWithEquityProps(userId, firstTitle, pageNo, pageSize);
    }

    @Override
    public List<CollectionByUserVO> collectionByUser(Long userId, String firstTitle) {
        return userInfoDao.collectionByUser(userId, firstTitle);
    }

    @Override
    public List<CollectionByUserDetailVO> collectionByUserDetail(Long userId, Long collectionId) {
        return userInfoDao.collectionByUserDetail(userId, collectionId);
    }

    @Override
    public Page<UserManageDaoVO> mateDaoUserList(UserManageDaoDTO userManageDaoDTO) {
        Page<UserManageDaoVO> userManageDaoVOPage = userInfoDao.mateDaoUserList(userManageDaoDTO);
        userManageDaoVOPage.getRecords().forEach(userManageDaoVO -> {
            UserCityServerCentre userCityServerCentre = userCityServerCentreDao.selectByUserId(userManageDaoVO.getId());
            userManageDaoVO.setUserCityServerCentre(userCityServerCentre);
        });
        return userManageDaoVOPage;
    }

    @Override
    public List<UserWithCollectionSimpleVO> userWithCollectionExport(MarketTypeEnum marketType) {
        List<UserWithCollectionSimpleVO> result = secondCollectionConfigDao.getCollectionIdList(marketType.getCode());
        List<Long> collectionIdList = result.stream().map(UserWithCollectionSimpleVO::getCollectionId).collect(Collectors.toList());
        if (CollUtil.isEmpty(result)) {
            return new ArrayList<>();
        }
        //市值持仓账号
        List<Long> userIdList = filterIncomeListDao.getMarketAccountIds();
        //计算销毁量
        List<UserWithCollectionSimpleVO> destroyCount = userInfoDao.getDestroyCount(collectionIdList);
        Map<Long, String> destroyCountMap = destroyCount.stream().collect(Collectors.toMap(UserWithCollectionSimpleVO::getCollectionId, UserWithCollectionSimpleVO::getDestroyCount));
        //计算流通数量(所有流通数量 - 市值持仓数量)
        List<UserWithCollectionSimpleVO> countCollection = userInfoDao.countCollection(collectionIdList);
        List<UserWithCollectionSimpleVO> marketAccountCollection = userInfoDao.marketAccountCollection(collectionIdList, userIdList);
        Map<Long, String> countCollectionMap = countCollection.stream().collect(Collectors.toMap(UserWithCollectionSimpleVO::getCollectionId, UserWithCollectionSimpleVO::getCountCollection));
        Map<Long, String> marketAccountCollectionMap = marketAccountCollection.stream().collect(Collectors.toMap(UserWithCollectionSimpleVO::getCollectionId, UserWithCollectionSimpleVO::getMarketAccountCollection));

        //藏品对应持仓人数
        //sql 中 in 条数太多sql效率很低 用单条 = 循环查询接口响应太慢 所以每次取5条处理
        List<Long> fiveCollectionIdList = Lists.newArrayList();
        List<UserWithCollectionSimpleVO> userCount = Lists.newArrayList();
        List<UserWithCollectionSimpleVO> marketAccountCount = Lists.newArrayList();
        int count = 0;
        for (int i = 0; i < collectionIdList.size(); i++) {
            fiveCollectionIdList.add(collectionIdList.get(i));
            count++;
            //满五条或者结束循环时去处理
            if (count == 5 || i == (collectionIdList.size() - 1)) {
                userCount.addAll(userInfoDao.userCount(fiveCollectionIdList));
                marketAccountCount.addAll(userInfoDao.marketAccountCount(fiveCollectionIdList, userIdList));
                fiveCollectionIdList.clear();
                count = 0;
            }

        }
        Map<Long, String> userCountMap = userCount.stream().collect(Collectors.toMap(UserWithCollectionSimpleVO::getCollectionId, UserWithCollectionSimpleVO::getCountUser));
        Map<Long, String> marketAccountCountMap = marketAccountCount.stream().collect(Collectors.toMap(UserWithCollectionSimpleVO::getCollectionId, UserWithCollectionSimpleVO::getCountUser));
        for (UserWithCollectionSimpleVO data : result) {
            //计算持仓人数（所有持仓 - 市值持仓人数）
            Integer userCountValue = Integer.parseInt(ObjectUtil.isNull(userCountMap.get(data.getCollectionId())) ? "0" : userCountMap.get(data.getCollectionId())) - Integer.parseInt(ObjectUtil.isNull(marketAccountCountMap.get(data.getCollectionId())) ? "0" : marketAccountCountMap.get(data.getCollectionId()));
            data.setCountUser(userCountValue.toString());
            //销毁
            data.setDestroyCount(ObjectUtil.isNull(destroyCountMap.get(data.getCollectionId())) ? "0" : destroyCountMap.get(data.getCollectionId()));
            //市值持仓数量
            data.setMarketAccountCollection(ObjectUtil.isNull(marketAccountCollectionMap.get(data.getCollectionId())) ? "0" : marketAccountCollectionMap.get(data.getCollectionId()));
            //流通数量(所有流通数量 - 市值持仓数量)
            Integer countCollectionValue = Integer.parseInt(ObjectUtil.isNull(countCollectionMap.get(data.getCollectionId())) ? "0" : countCollectionMap.get(data.getCollectionId())) - Integer.parseInt(data.getMarketAccountCollection());
            data.setCountCollection(countCollectionValue.toString());
        }
        return result;
    }

    @Override
    public Boolean saveDaoUserIsPartner(Long idRequest) {
        UserInfo userInfo = userInfoDao.getById(idRequest);
        Boolean isPartner = userInfo.getIsPartner();
        return userInfoDao.updateIsPartner(idRequest, isPartner ? 0 : 1);
    }

    /**
     * 马特DAO-用户列表,某个用户详情
     *
     * @param userMangeDaoUserInfoDTO
     * @return
     */
    @Override
    public UserMangeDaoUserInfoVO userMangeDaoUserInfo(UserMangeDaoUserInfoDTO userMangeDaoUserInfoDTO) {
        if (BeanUtil.isEmpty(userMangeDaoUserInfoDTO)) {
            throw new GlobalRunTimeException("参数不可以全部为null");
        }
        UserInfo userInfo = null;
        if (!userMangeDaoUserInfoDTO.getUserTel().equals("")) {
            QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
            userInfoQueryWrapper.eq("user_tel", userMangeDaoUserInfoDTO.getUserTel());
            userInfo = userInfoDao.getOne(userInfoQueryWrapper);
        }
        if (BeanUtil.isEmpty(userInfo)) {
            throw new GlobalRunTimeException("用户不存在");
        }
        // 用户的邀请人id集合（溯源链 可以追源头）
        String recommendUserIdList = userInfo.getRecommendUserIdList();
        // 组装用户的查询逻辑 判定溯源链是否为空,如不为空的话,则使用严谨性更加强的溯源链组装
        if (StrUtil.equals(recommendUserIdList, "0")) {
            // 为0则证明该用户是顶级,则直接赋值顶级溯源链
            recommendUserIdList = Convert.toStr(userInfo.getId());
        } else {
            // 非顶级溯源链,和自己所在的溯源链进行组合,拼装为 溯源链,自己的id.    用以该溯源链溯源下属的直推用户
            recommendUserIdList = StrUtil.format("{},{}", recommendUserIdList, Convert.toStr(userInfo.getId()));
        }
        UserMangeDaoUserInfoVO userMangeDaoUserInfoVOPage = userInfoDao.userMangeDaoUserInfo(userMangeDaoUserInfoDTO.getUserTel(), recommendUserIdList);
        return userMangeDaoUserInfoVOPage;
    }

    /**
     * 马特DAO-推广奖励列表
     *
     * @param promotionRewardsDTO
     * @return
     */
    @Override
    public Page<PromotionRewardsVO> promotionRewards(PromotionRewardsDTO promotionRewardsDTO) {
        return userInfoDao.promotionRewards(promotionRewardsDTO);
    }

    @Override
    public void updateUserInformation(Long id, String nickName, String avatarImg, Boolean isFreeze, Boolean giftPermission) {
        userInfoDao.updateUserInformation(id, nickName, avatarImg, isFreeze, giftPermission);
    }

    @Override
    public Page<UserInfo> airdropGrantUser(int pageNo, int pageSize, String nickName, String userUuid, String userTel) {
        return userInfoDao.airdropGrantUser(pageNo, pageSize, nickName, userUuid, userTel);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SubmitRealNameVO submitRealName(UserInfo user, String name, String cardId) throws IOException {
        SubmitRealNameVO submitRealNameVO = new SubmitRealNameVO();
        IdRequest idRequest = new IdRequest();
        idRequest.setId(user.getId());
        List<IdcardInfo> list = idcardInfoDao.findListByUserIdAndIsPass(user.getId(), IdCardIsPassTypeEnum.UNDER_REVIEW.getCode());
        if (list.size() >= 1) {
            submitRealNameVO.setFlag(true);
            List<FaceCheckRecord> newByUserId = faceCheckRecordDao.getNewByUserId(user.getId());
            if (CollectionUtils.isEmpty(newByUserId) || newByUserId.get(0).getCheckStatus() != 0) {
                FaceCheckRecord faceCheckRecord = new FaceCheckRecord();
                faceCheckRecord.setUserId(user.getId());
                faceCheckRecord.setCheckStatus(0);
                faceCheckRecord.insert();
            }
            String faceCheckUrl = shuJuBaoCloudFeign.liveDetection(idRequest);
            if (StringUtils.isEmpty(faceCheckUrl)) {
                throw new GlobalRunTimeException("系统繁忙,请稍后重试");
            }
            submitRealNameVO.setFaceCheckUrl(faceCheckUrl);
            return submitRealNameVO;
        }
        //如果用户是市值账号,则不允许实名认证
        if (filterIncomeListDao.getIsContainsUserId(user.getId())) {
            throw new GlobalRunTimeException(ErrorCode.NO_ROLE);
        }
        boolean validCard = IdcardUtil.isValidCard(cardId);
        if (!validCard) {
            throw new GlobalRunTimeException(ErrorCode.ID_CARD_FORMAT_ERROR);
        }
        if (user.getIsSm()) {
            throw new GlobalRunTimeException(ErrorCode.THE_CURRENT_ACCOUNT_HAS_BEEN_AUTHENTICATED);
        }
        CommonResult<Boolean> logOffKeyExists = userLogOffRecordClient.logOffKeyExists(cardId);
        if (BooleanUtil.isTrue(logOffKeyExists.getData())) {
            throw new GlobalRunTimeException("距离上次注销不满3个月，禁止实名！");
        }

        int ageByIdCard = IdcardUtil.getAgeByIdCard(cardId);
        if (ageByIdCard < 18 || ageByIdCard > 70) {
            throw new GlobalRunTimeException("仅支持年满18周岁至65周岁");
        }

        List<IdcardInfo> cardIds = idcardInfoDao.findByCardId(cardId);
        if (cardIds.size() >= 1) {
            throw new GlobalRunTimeException("该身份已实名");
        }
        String key = RedisKeyEnum.REAL_NAME_TIME.getKey() + user.getId();
        Long increment = redisTemplate.opsForValue().increment(key);
        redisTemplate.expire(key, 1, TimeUnit.HOURS);
        if (increment > 10) {
            throw new GlobalRunTimeException("实名次数过多，请稍后再试");
        }
        RealNameVerificationDTO realNameVerificationDTO = new RealNameVerificationDTO();
        realNameVerificationDTO.setIdCardNo(cardId);
        realNameVerificationDTO.setName(name);
        RealNameVerificationVO realNameVerificationVO = shuJuBaoCloudFeign.realNameVerification(realNameVerificationDTO);
        if (ObjectUtil.isNull(realNameVerificationVO)) {
            throw new GlobalRunTimeException("系统繁忙,请稍后重试");
        }
        if ("10000".equals(realNameVerificationVO.getCode())) {
            RealNameVerificationData data = realNameVerificationVO.getData();
            IdcardInfo idcardInfo = new IdcardInfo();
            idcardInfo.setUserId(user.getId());
            idcardInfo.setCardId(cardId);
            idcardInfo.setName(name);
            if ("1".equals(data.getResult())) {
                StaticData face_is_close = staticDataDao.getByType("face_is_close");
                if (StrUtil.equals(face_is_close.getValue(), "1")) {
                    idcardInfo.setIsPass(IdCardIsPassTypeEnum.UNDER_REVIEW.getCode());
//                    JSONObject idCardInfor = result.getJSONObject("IdCardInfor");
//                    idcardInfo.setSex(idCardInfor.getString("sex"));
//                    idcardInfo.setAddress(idCardInfor.getString("area"));
//                    idcardInfo.setBirthDay(idCardInfor.getString("birthday"));
                    idcardInfo.insert();
                    submitRealNameVO.setFlag(Boolean.TRUE);
                    //获取人脸校验的url
                    List<FaceCheckRecord> newByUserId = faceCheckRecordDao.getNewByUserId(user.getId());
                    if (CollectionUtils.isEmpty(newByUserId) || newByUserId.get(0).getCheckStatus() != 0) {
                        FaceCheckRecord faceCheckRecord = new FaceCheckRecord();
                        faceCheckRecord.setUserId(user.getId());
                        faceCheckRecord.setCheckStatus(0);
                        faceCheckRecord.insert();
                    }
                    String faceCheckUrl = shuJuBaoCloudFeign.liveDetection(idRequest);
                    if (StringUtils.isEmpty(faceCheckUrl)) {
                        throw new GlobalRunTimeException("系统繁忙,请稍后重试");
                    }
                    submitRealNameVO.setFaceCheckUrl(faceCheckUrl);
                } else {
                    idcardInfo.setIsPass(IdCardIsPassTypeEnum.SUCCESS.getCode());
//                    JSONObject idCardInfor = result.getJSONObject("IdCardInfor");
//                    idcardInfo.setSex(idCardInfor.getString("sex"));
//                    idcardInfo.setAddress(idCardInfor.getString("area"));
//                    idcardInfo.setBirthDay(idCardInfor.getString("birthday"));
                    idcardInfo.insert();
                    user.setIsSm(Boolean.TRUE);
                    userInfoDao.updateIsSm(user.getId(), user.getIsSm());
                    userReceiveIntegralService.completeOtherIntegralTask(user.getId(), IntegralTaskEnum.REAL_NAME, AssetChangeLogEnum.REAL_NAME);
                    messageQueueHelper.sendMessage(MessageTopic.USER_AUTH_TOPIC, idcardInfo);
                    submitRealNameVO.setFlag(Boolean.FALSE);
                }
            } else {
                throw new GlobalRunTimeException(ErrorCode.NAME_AND_ID_NUMBER_ARE_INCONSISTENT);
            }
        } else {
            throw new GlobalRunTimeException("身份库查无此人");
        }
        return submitRealNameVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HwCheckVO verifyFace(UserInfo userInfo, String videoBase64, String actions) {
        Assert.isFalse(userInfo.getIsSm(), () -> new GlobalRunTimeException("您已完成实名认证"));
        List<IdcardInfo> listByUserIdAndIsPass = idcardInfoDao.findListByUserIdAndIsPass(userInfo.getId(), IdCardIsPassTypeEnum.UNDER_REVIEW.getCode());

        if (CollUtil.isEmpty(listByUserIdAndIsPass)) {
            throw new GlobalRunTimeException("未找到实名记录，请重新填写");
        }
        String key = RedisKeyEnum.REAL_FACE_TIME.getKey() + userInfo.getId();
        Long increment = redisTemplate.opsForValue().increment(key);
        redisTemplate.expire(key, 1, TimeUnit.HOURS);
        if (increment > 10) {
            throw new GlobalRunTimeException("失败次数过多，请稍后再试");
        }
        HwCheckDTO hwCheckDTO = new HwCheckDTO();
        hwCheckDTO.setIdentityId(listByUserIdAndIsPass.get(0).getCardId());
        hwCheckDTO.setName(listByUserIdAndIsPass.get(0).getName());
        hwCheckDTO.setVideoBase64(videoBase64);
        hwCheckDTO.setActions(actions);
        Result<HwCheckVO> hwCheckVOResult = hwCloudFeign.checkUserReal(hwCheckDTO);
        if (hwCheckVOResult.getCode() != 0) {
            throw new GlobalRunTimeException(hwCheckVOResult.getMessage());
        }
        if (hwCheckVOResult.getData().getStatus() == true) {
            userInfo.setIsSm(Boolean.TRUE);
            userInfoDao.updateIsSm(userInfo.getId(), userInfo.getIsSm());
            listByUserIdAndIsPass.get(0).setIsPass(IdCardIsPassTypeEnum.SUCCESS.getCode());
            listByUserIdAndIsPass.get(0).updateById();
            //用户实名成功后添加积分
            userReceiveIntegralService.completeOtherIntegralTask(userInfo.getId(), IntegralTaskEnum.REAL_NAME, AssetChangeLogEnum.REAL_NAME);
            messageQueueHelper.sendMessage(MessageTopic.USER_AUTH_TOPIC, listByUserIdAndIsPass.get(0));
            return hwCheckVOResult.getData();
        } else {
            throw new GlobalRunTimeException("人脸识别失败：" + hwCheckVOResult.getData().getResult());
        }
    }


    /**
     * 获取人脸检测Url
     *
     * @param userInfo
     * @return
     */
    @Override
    public String faceVerificationUrl(UserInfo userInfo) {
        Assert.isFalse(userInfo.getIsSm(), () -> new GlobalRunTimeException("您已完成实名认证"));
        List<IdcardInfo> listByUserIdAndIsPass = idcardInfoDao.findListByUserIdAndIsPass(userInfo.getId(), IdCardIsPassTypeEnum.UNDER_REVIEW.getCode());

        if (CollUtil.isEmpty(listByUserIdAndIsPass)) {
            throw new GlobalRunTimeException("未找到实名记录，请重新填写");
        }
        String key = RedisKeyEnum.REAL_FACE_TIME.getKey() + userInfo.getId();
        Long increment = redisTemplate.opsForValue().increment(key);
        redisTemplate.expire(key, 1, TimeUnit.HOURS);
        if (increment > 10) {
            throw new GlobalRunTimeException("失败次数过多，请稍后再试");
        }
        List<FaceCheckRecord> newByUserId = faceCheckRecordDao.getNewByUserId(userInfo.getId());
        if (CollectionUtils.isEmpty(newByUserId) || newByUserId.get(0).getCheckStatus() != 0) {
            FaceCheckRecord faceCheckRecord = new FaceCheckRecord();
            faceCheckRecord.setUserId(userInfo.getId());
            faceCheckRecord.setCheckStatus(0);
            faceCheckRecord.insert();
        }
        IdRequest idRequest = new IdRequest();
        idRequest.setId(userInfo.getId());
        return shuJuBaoCloudFeign.liveDetection(idRequest);
    }


    /**
     * 获取人脸回调是否为初始化状态
     *
     * @return
     */
    @Override
    public ShuJuBaoFaceGetInitVO faceGetInit() {
        ShuJuBaoFaceGetInitVO shuJuBaoFaceGetInitVO = new ShuJuBaoFaceGetInitVO();
        UserInfo user = UserPool.getUser();
        List<FaceCheckRecord> newByUserId = faceCheckRecordDao.getNewByUserId(user.getId());
        if (!CollectionUtils.isEmpty(newByUserId) && newByUserId.get(0).getCheckStatus() == 0) {
            shuJuBaoFaceGetInitVO.setStatus(Boolean.TRUE);
        }
        return shuJuBaoFaceGetInitVO;
    }

    /**
     * 人脸检测回调
     *
     * @param shuJuBaoLiveDetectionVO
     * @return
     */
    @Override
    public ShuJuBaoFaceCheckVO faceVerificationCallBack(ShuJuBaoLiveDetectionVO shuJuBaoLiveDetectionVO) {
        Assert.notNull(shuJuBaoLiveDetectionVO, () -> new GlobalRunTimeException("回调参数不能为空"));
        //请求的时候存入的是用户的id
        String serialNumber = shuJuBaoLiveDetectionVO.getSerialNumber();
        Assert.isFalse(StringUtils.isEmpty(serialNumber), () -> new GlobalRunTimeException("用户id为空"));
        UserInfo userInfo = userInfoDao.getById(Long.valueOf(serialNumber));
        Assert.notNull(userInfo, () -> new GlobalRunTimeException("用户不存在"));
        Assert.isFalse(userInfo.getIsSm(), () -> new GlobalRunTimeException("您已完成实名认证"));
        if (!"1".equals(shuJuBaoLiveDetectionVO.getBackResult())) {
            FaceCheckRecord faceCheckRecord = assembledFaceCheckRecord(userInfo.getId(), "人脸检测失败", 1, JSONObject.toJSONString(shuJuBaoLiveDetectionVO));
            faceCheckRecord.insertOrUpdate();
            throw new GlobalRunTimeException("人脸检测失败");
        }
        List<IdcardInfo> listByUserIdAndIsPass = idcardInfoDao.findListByUserIdAndIsPass(userInfo.getId(), IdCardIsPassTypeEnum.UNDER_REVIEW.getCode());
        if (CollUtil.isEmpty(listByUserIdAndIsPass)) {
            FaceCheckRecord faceCheckRecord = assembledFaceCheckRecord(userInfo.getId(), "未找到实名记录", 1, JSONObject.toJSONString(shuJuBaoLiveDetectionVO));
            faceCheckRecord.insertOrUpdate();
            throw new GlobalRunTimeException("未找到实名记录");
        }
        if (!"10000".equals(shuJuBaoLiveDetectionVO.getCode())) {
            FaceCheckRecord faceCheckRecord = assembledFaceCheckRecord(userInfo.getId(), ShuJuBaoFaceCheckVO.ShuJuBaoFaceCHeckCodeGetMessage(shuJuBaoLiveDetectionVO.getCode()), 1, JSONObject.toJSONString(shuJuBaoLiveDetectionVO));
            faceCheckRecord.insertOrUpdate();
            return ShuJuBaoFaceCheckVO.ShuJuBaoFaceCHeckCodeRet(shuJuBaoLiveDetectionVO.getCode());
        }
        shuJuBaoLiveDetectionVO.setName(listByUserIdAndIsPass.get(0).getName());
        shuJuBaoLiveDetectionVO.setIdCardNo(listByUserIdAndIsPass.get(0).getCardId());
        ShuJuBaoFaceCheckVO shuJuBaoFaceCheckVO = shuJuBaoCloudFeign.liveDetectionCallBack(shuJuBaoLiveDetectionVO);
        if (ObjectUtil.isNull(shuJuBaoFaceCheckVO) || shuJuBaoFaceCheckVO.getStatus().equals(Boolean.FALSE)) {
            FaceCheckRecord faceCheckRecord = assembledFaceCheckRecord(userInfo.getId(), ObjectUtil.isNull(shuJuBaoFaceCheckVO) ? "人脸比对失败" : shuJuBaoFaceCheckVO.getResult(), 1, JSONObject.toJSONString(shuJuBaoFaceCheckVO));
            faceCheckRecord.insertOrUpdate();
            return shuJuBaoFaceCheckVO;
        }
        FaceCheckRecord faceCheckRecord = assembledFaceCheckRecord(userInfo.getId(), shuJuBaoFaceCheckVO.getResult(), 2, JSONObject.toJSONString(shuJuBaoFaceCheckVO));
        faceCheckRecord.insertOrUpdate();
        //成功
        userInfo.setIsSm(Boolean.TRUE);
//        userInfo.updateById();
        userInfoDao.updateIsSm(userInfo.getId(), true);
        listByUserIdAndIsPass.get(0).setIsPass(IdCardIsPassTypeEnum.SUCCESS.getCode());
        listByUserIdAndIsPass.get(0).updateById();
        //用户实名成功后添加积分
        userReceiveIntegralService.completeOtherIntegralTask(userInfo.getId(), IntegralTaskEnum.REAL_NAME, AssetChangeLogEnum.REAL_NAME);
        messageQueueHelper.sendMessage(MessageTopic.USER_AUTH_TOPIC, listByUserIdAndIsPass.get(0));
        return shuJuBaoFaceCheckVO;
    }

    private FaceCheckRecord assembledFaceCheckRecord(Long userId, String checkMessage, Integer checkStatus, String checkResult) {
        List<FaceCheckRecord> newByUserId = faceCheckRecordDao.getNewByUserId(userId);
        if (CollectionUtils.isEmpty(newByUserId) || newByUserId.get(0).getCheckStatus() != 0) {
            FaceCheckRecord faceCheckRecord = new FaceCheckRecord();
            faceCheckRecord.setUserId(userId);
            faceCheckRecord.setCheckMessage(checkMessage);
            faceCheckRecord.setCheckStatus(checkStatus);
            faceCheckRecord.setCheckResult(checkResult);
            return faceCheckRecord;
        }
        FaceCheckRecord faceCheckRecord = newByUserId.get(0);
        faceCheckRecord.setCheckMessage(checkMessage);
        faceCheckRecord.setCheckStatus(checkStatus);
        faceCheckRecord.setCheckResult(checkResult);
        return faceCheckRecord;

    }


    private void threeElementsOfIdentityAuthentication(String name, String cardId, UserInfo user) throws IOException {
        Map params = new HashMap();
        params.put("mobile", user.getUserTel());
        params.put("name", name);
        params.put("idcard", cardId);
        String s1 = IdCardAuditUtil.get(params);
        JSONObject o = JSONObject.parseObject(s1, JSONObject.class);
        String code1 = o.getString("code");
        if (!code1.equals("200")) {
            throw new GlobalRunTimeException("手机号与身份信息不匹配");
        }
    }


    /**
     * 马特DAO-用户信息,直推列表
     *
     * @param maTeUserMangeDaoGeneralEarningsDirectlyDTO
     * @return
     */
    @Override
    public Page<MaTeUserMangeDaoGeneralEarningsDirectlyListVO> mateUserMangeDaoGeneralEarningsDirectlyList(MaTeUserMangeDaoGeneralEarningsDirectlyDTO maTeUserMangeDaoGeneralEarningsDirectlyDTO) {
        if (BeanUtil.isEmpty(maTeUserMangeDaoGeneralEarningsDirectlyDTO)) {
            throw new GlobalRunTimeException("参数不可以全部为null");
        }
        UserInfo userInfo = null;
        if (!maTeUserMangeDaoGeneralEarningsDirectlyDTO.getUserTel().equals("")) {
            QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
            userInfoQueryWrapper.eq("user_tel", maTeUserMangeDaoGeneralEarningsDirectlyDTO.getUserTel());
            userInfo = userInfoDao.getOne(userInfoQueryWrapper);
        }
        // 根据手机号拿到用户的查询id
        if (BeanUtil.isEmpty(userInfo)) {
            throw new GlobalRunTimeException("用户不存在");
        }
        Page<MaTeUserMangeDaoGeneralEarningsDirectlyListVO> maTeUserMangeDaoGeneralEarningsDirectlyListVOPage = userInfoDao.mateUserMangeDaoGeneralEarningsDirectlyList(maTeUserMangeDaoGeneralEarningsDirectlyDTO.toMp(), userInfo.getId());
        return maTeUserMangeDaoGeneralEarningsDirectlyListVOPage;
    }

    @Override
    public Page<MaTeUserMangeDaoGeneralEarningsIndirectListVO> maTeUserMangeDaoGeneralEarningsIndirectList(MaTeUserMangeDaoGeneralEarningsDirectlyDTO maTeUserMangeDaoGeneralEarningsDirectlyDTO) {
        if (BeanUtil.isEmpty(maTeUserMangeDaoGeneralEarningsDirectlyDTO)) {
            throw new GlobalRunTimeException("参数不可以全部为null");
        }
        UserInfo userInfo = null;
        if (!maTeUserMangeDaoGeneralEarningsDirectlyDTO.getUserTel().equals("")) {
            QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
            userInfoQueryWrapper.eq("user_tel", maTeUserMangeDaoGeneralEarningsDirectlyDTO.getUserTel());
            userInfo = userInfoDao.getOne(userInfoQueryWrapper);
        }
        // 根据手机号拿到用户的查询id
        if (BeanUtil.isEmpty(userInfo)) {
            throw new GlobalRunTimeException("用户不存在");
        }
        Page<MaTeUserMangeDaoGeneralEarningsIndirectListVO> maTeUserMangeDaoGeneralEarningsIndirectListVOPage = userInfoDao.maTeUserMangeDaoGeneralEarningsIndirectList(maTeUserMangeDaoGeneralEarningsDirectlyDTO.toMp(), userInfo.getId());
        return maTeUserMangeDaoGeneralEarningsIndirectListVOPage;
    }

    /**
     * 用户收益列表
     *
     * @param earningsListDTO
     * @return
     */
    @Override
    public Page<UserInfoEarningsVO> userInfoEarningsList(EarningsListDTO earningsListDTO) {
        if (BeanUtil.isEmpty(earningsListDTO)) {
            throw new GlobalRunTimeException("参数不可以全部为null");
        }
        UserInfo userInfo = null;
        if (!earningsListDTO.getUserTel().equals("")) {
            QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
            userInfoQueryWrapper.eq("user_tel", earningsListDTO.getUserTel());
            userInfo = userInfoDao.getOne(userInfoQueryWrapper);
        }
        // 根据手机号拿到用户的查询id
        if (BeanUtil.isEmpty(userInfo)) {
            throw new GlobalRunTimeException("用户不存在");
        }
        earningsListDTO.setId(userInfo.getId());
        return userInfoDao.userInfoEarningsList(earningsListDTO);
    }

    @Override
    public CalculationRewardVO calculationReward(CalculationRewardDTO calculationRewardDTO) {
        QueryWrapper<DaoLevelIncomeDetails> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("income_type", calculationRewardDTO.getType());
        DaoLevelIncomeDetails daoLevelIncomeDetails = (DaoLevelIncomeDetails) new DaoLevelIncomeDetails().selectOne(queryWrapper);
        if (!calculationRewardDTO.getType().equals(44)) {
            // 获取所有用户人数
            QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("is_partner", 1);
            Integer sum = userInfoDao.count(wrapper);
            if (sum <= 0) {
                throw new GlobalRunTimeException("当前不存在合伙人");
            }
            CalculationRewardVO calculationRewardVO = new CalculationRewardVO();
            calculationRewardVO.setRewardProportion(daoLevelIncomeDetails.getIncomePercentage().stripTrailingZeros().toPlainString());
            calculationRewardVO.setNumberAwards(calculationRewardDTO.getNumberAwards());
            calculationRewardVO.setRewardCapita(calculationRewardDTO.getNumberAwards().multiply(daoLevelIncomeDetails.getIncomePercentage().divide(Convert.toBigDecimal(100), 2, BigDecimal.ROUND_DOWN)).divide(Convert.toBigDecimal(sum), 2, BigDecimal.ROUND_DOWN).stripTrailingZeros().toPlainString());
            return calculationRewardVO;
        }
        QueryWrapper<UserCityServerCentre> userCityServerCentreQueryWrapper = new QueryWrapper<>();
        List<UserCityServerCentre> list = (List<UserCityServerCentre>) new UserCityServerCentre().selectList(userCityServerCentreQueryWrapper);
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.in("id", list.stream().map(UserCityServerCentre::getUserId).collect(Collectors.toList()));
        Integer userCityServerCentreQueryCount = userInfoDao.count(wrapper);
        if (userCityServerCentreQueryCount <= 0) {
            throw new GlobalRunTimeException("当前没有用户服务中心");
        }
        CalculationRewardVO calculationRewardVO = new CalculationRewardVO();
        calculationRewardVO.setRewardProportion(daoLevelIncomeDetails.getIncomePercentage().stripTrailingZeros().toPlainString());
        calculationRewardVO.setNumberAwards(calculationRewardDTO.getNumberAwards());
        calculationRewardVO.setRewardCapita(calculationRewardDTO.getNumberAwards().multiply(daoLevelIncomeDetails.getIncomePercentage().divide(Convert.toBigDecimal(100), 2, BigDecimal.ROUND_DOWN)).divide(Convert.toBigDecimal(userCityServerCentreQueryCount), 2, BigDecimal.ROUND_DOWN).stripTrailingZeros().toPlainString());
        return calculationRewardVO;
    }

    /**
     * 发放奖励
     *
     * @param distributionRewardsDTO
     * @return
     */
    @Override
    public Boolean distributionRewards(DistributionRewardsDTO distributionRewardsDTO) {
        // 发放奖励逻辑-  写入表sc_user_wallet余额   写入sc_user_wallet_detail日志 写入sc_user_income_record日志.  比例按照百分之60写死. 获取所有合伙人平分钱.保留两位小数
        QueryWrapper<DaoLevelIncomeDetails> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("income_type", distributionRewardsDTO.getType());
        DaoLevelIncomeDetails daoLevelIncomeDetails = (DaoLevelIncomeDetails) new DaoLevelIncomeDetails().selectOne(queryWrapper);
        // 所有人分的钱
        BigDecimal numberAwards = distributionRewardsDTO.getNumberAwards().multiply(daoLevelIncomeDetails.getIncomePercentage().divide(Convert.toBigDecimal(100)));

        List<UserInfo> userInfos = null;
        if (distributionRewardsDTO.getType().equals(IncomeTypeEnum.PLATFORM_PROFIT.getCode()) || distributionRewardsDTO.getType().equals(IncomeTypeEnum.PLATFORM_MARKET_VALUE_INCOME.getCode())) {
            // 获取为合伙人的所有人的数据,让后用numberAwards/size  获得每个人应得多少钱
            QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("is_partner", 1);
            userInfos = userInfoDao.list(wrapper);
        }

        // 城市服务中心ip分红,获取的用户数据通过sql来走
        if (distributionRewardsDTO.getType().equals(IncomeTypeEnum.CITY_IP_SERVER_SALES.getCode())) {
            userInfos = userInfoDao.getUserCityServerCentre();
        }

        if (CollUtil.isEmpty(userInfos)) {
            throw new GlobalRunTimeException("暂无合伙人");
        }

        // 计算每个人平分的钱
        BigDecimal distributionMoney = numberAwards.divide(Convert.toBigDecimal(userInfos.size())).setScale(2, BigDecimal.ROUND_DOWN);

        // 开始处理每个人分到的钱和日志
        userInfos.forEach(userInfo -> {
            QueryWrapper<UserWallet> lambdaQueryWrapper = new QueryWrapper();
            UserWallet userWallet = (UserWallet) new UserWallet().selectOne(lambdaQueryWrapper.eq("user_id", userInfo.getId()));
            // 用户加钱
            userWalletDao.addIncome(userInfo.getId(), distributionMoney);
            // 写入sc_user_wallet_detail日志
            UserWalletDetail userWalletDetail = new UserWalletDetail();
            userWalletDetail.setType(WalletDetailTypeEnum.INCOME);
            userWalletDetail.setAmount(distributionMoney);
            userWalletDetail.setCharge(new BigDecimal("0"));
            userWalletDetail.setUserId(userInfo.getId());
            userWalletDetail.setRealAmount(distributionMoney);
            userWalletDetail.setAfterBalance(userWallet.getBalance().add(distributionMoney));
            userWalletDetail.setBeforeBalance(userWallet.getBalance());
            userWalletDetail.setIsAdd(true);
            userWalletDetailDao.insert(userWalletDetail);
            // 写入sc_user_income_record日志
            UserIncomeRecord userIncomeRecord = new UserIncomeRecord();
            userIncomeRecord.setAmount(distributionMoney);
            userIncomeRecord.setUserId(userInfo.getId());
            userIncomeRecord.setIncomeType(IncomeTypeEnum.getById(distributionRewardsDTO.getType()));
            userIncomeRecord.setIncomeTypeName(IncomeTypeEnum.getById(distributionRewardsDTO.getType()).getDescription());
            userIncomeRecord.setIncomeHierarchy(IncomeHierarchyEnum.SPECIAL);
            userIncomeRecord.setIncomeHierarchyName(IncomeHierarchyEnum.SPECIAL.getDescription());
            userIncomeRecord.setIncomeCardinality(distributionRewardsDTO.getNumberAwards());
            userIncomeRecord.setIncomeProportion(daoLevelIncomeDetails.getIncomePercentage().stripTrailingZeros().toPlainString());
            userIncomeRecord.setSourceUserId(0L);
            userIncomeRecord.setIncomeUserNum("0");
            userIncomeRecord.setWeightsNum("0");
            userIncomeRecord.setCreateTime(new Date());
            userIncomeRecord.setModifyTime(new Date());
            userIncomeRecord.setOrderNo("");
            userIncomeRecord.setIsDelete(false);
            userIncomeRecord.insert();
        });
        return true;
    }

    @Override
    public InterestsListVO interestsList() {
        List<DaoLevelIncomeDetails> userIncomeRecord = (List<DaoLevelIncomeDetails>) new DaoLevelIncomeDetails().selectList(new QueryWrapper());
        //居民
        List<DaoLevelIncomeDetails> resident = new ArrayList<>();
        //城主
        List<DaoLevelIncomeDetails> castellan = new ArrayList<>();
        List<DaoLevelIncomeDetails> cityService = new ArrayList<>();
        List<DaoLevelIncomeDetails> communityStudio = new ArrayList<>();
        userIncomeRecord.forEach(daoLevelIncomeDetails -> {
            if (daoLevelIncomeDetails.getDaoLevelName().equals("居民")) {
                resident.add(daoLevelIncomeDetails);
            } else if (daoLevelIncomeDetails.getDaoLevelName().equals("城主")) {
                castellan.add(daoLevelIncomeDetails);
            } else if (daoLevelIncomeDetails.getDaoLevelName().equals("城市服务中心")) {
                cityService.add(daoLevelIncomeDetails);
            } else if (daoLevelIncomeDetails.getDaoLevelName().equals("社区工作室")) {
                communityStudio.add(daoLevelIncomeDetails);
            }
        });
        InterestsListVO interestsListVO = new InterestsListVO();
        interestsListVO.setResident(resident);
        interestsListVO.setCastellan(castellan);
        interestsListVO.setCityService(cityService);
        interestsListVO.setCommunityStudio(communityStudio);
        return interestsListVO;
    }

    @Override
    public Boolean interestsSave(List<InterestsSaveDTO> interestsSaveDTO) {
        interestsSaveDTO.forEach(save -> {
            UpdateWrapper<DaoLevelIncomeDetails> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", save.getId());
            updateWrapper.set("income_percentage", save.getIncomePercentage());
            new DaoLevelIncomeDetails().update(updateWrapper);
        });
        return true;
    }

    /**
     * 特殊奖励
     *
     * @param specialRewardDTO
     * @return
     */
    @Override
    public Page<SpecialRewardVO> specialReward(SpecialRewardDTO specialRewardDTO) {
        return userInfoDao.specialReward(specialRewardDTO);
    }

    @Override
    public UserPrivilegeVO userPrivilege() {
        UserPrivilegeVO userPrivilegeVO = new UserPrivilegeVO();
        UserInfo user = UserPool.getUser();
        if (user.getPrivilegeLevel() <= 0) {
            throw new GlobalRunTimeException("暂无特权");
        }
        DigitalCollection digitalCollection = digitalCollectionDao.getPrivilegeLevel(user.getPrivilegeLevel());
        Privilege privilege = privilegeDao.getByCollectionId(digitalCollection.getId());
        if (ObjectUtil.isEmpty(privilege) || ObjectUtil.isEmpty(digitalCollection)) {
            throw new GlobalRunTimeException("暂无特权");
        }
        //用户拥有的所有特权藏品
        List<UserCollection> list = userCollectionDao.getAllPrivilegeByUserId(user.getId());
        Integer count = 0;
        for (UserCollection userCollection : list) {
            Privilege byCollectionId = privilegeDao.getByCollectionId(userCollection.getCollectionId());
            count = count + byCollectionId.getFirstPayTime();
        }
        userPrivilegeVO.setFirstPayTime(count);
        userPrivilegeVO.setIsAirdrop(privilege.getIsAirdrop());
        userPrivilegeVO.setIsIpShare(privilege.getIsIpShare());
        userPrivilegeVO.setPrivilegeName(privilege.getName());
        int lastFirstPayTime = privilegeUseLogService.getLastFirstPayTime(user.getId());
        userPrivilegeVO.setRemainingNum(lastFirstPayTime);
        BigDecimal transferDiscount = privilege.getTransferDiscount();
        String s = transferDiscount.movePointRight(1).stripTrailingZeros().toPlainString();
        userPrivilegeVO.setTransferDiscount(s);
        userPrivilegeVO.setPrivilegeLevel(digitalCollection.getPrivilegeLevel());
        return userPrivilegeVO;
    }

    @Override
    public Page<SimpleUserVO> simpleUserList(String userTel, int pageNo, int pageSize) {
        return userInfoDao.simpleUserList(userTel, pageNo, pageSize);
    }

    @Override
    public List<Long> userRelevanceByUserId(Long userId) {
        return userRelevanceService.userRelevanceByUserId(userId);
    }

    @Override
    public Boolean verificationUserInfoExistCapitalPassWord() {
        return StrUtil.isNotEmpty(UserPool.getUser().getTransactionPassword());
    }

    @Override
    public UserHomeVO getUserHome() {
        UserInfo user = UserPool.getUser();
        if (BeanUtil.isEmpty(user)) {
            return null;
        }
        UserHomeVO userHomeVO = new UserHomeVO();
        userHomeVO.setNickName(user.getNickName());
        userHomeVO.setAvatarImg(user.getAvatarImg());
        userHomeVO.setId(user.getId());
        UserChainInfo byUserId = userChainInfoService.getByUserId(user.getId());
        if (BeanUtil.isEmpty(byUserId) || StrUtil.isEmpty(byUserId.getAddress())) {
            userHomeVO.setAddress("");
        } else {
            userHomeVO.setAddress(byUserId.getAddress());
        }
        return userHomeVO;
    }

    @Override
    public void userResetBankInfo(UserResetBankInfoDTO userResetBankInfoDTO) {
        // 指定后台管理用户账号才可以操作
        if (!SysMemberPool.getMember().getId().equals(1L) && !SysMemberPool.getMember().getId().equals(12L) && !SysMemberPool.getMember().getId().equals(8L)) {
            throw new GlobalRunTimeException("该用户无操作权限");
        }
        UserInfo oneByUserTel = userInfoDao.getOneByUserTel(userResetBankInfoDTO.getUserTel());
        if (BeanUtil.isEmpty(oneByUserTel)) {
            throw new GlobalRunTimeException("用户不存在");
        }

        UserHnaExt byUserId = userHnaExtDao.getByUserId(oneByUserTel.getId());
        if (BeanUtil.isNotEmpty(byUserId) && !byUserId.getStatus().equals(AccountStatusEnum.FAIl)) {
            throw new GlobalRunTimeException("用户已绑定汇付开户,无法进行后续操作.联系后台人员询问处理方式.");
        }

        LlUserExt llUserExt = llUserExtDao.getByUserId(oneByUserTel.getId());
        if (BeanUtil.isNotEmpty(llUserExt) && !llUserExt.getStatus().equals(AccountStatusEnum.FAIl)) {
            throw new GlobalRunTimeException("用户已绑定连连开户,无法进行后续操作.联系后台人员询问处理方式.");
        }

        if (oneByUserTel.getSandAccountOpen() || oneByUserTel.getSandFaceVerify() || oneByUserTel.getSandPayPwd()) {
            throw new GlobalRunTimeException("用户已绑定杉德开户,无法进行后续操作.联系后台人员询问处理方式.");
        }
        // 用户绑定的银行卡.
        List<UserBankCard> userBankCards = userBankCardDao.getByUserId(oneByUserTel.getId());
        if (CollUtil.isNotEmpty(userBankCards)) {
            String bankInfo = "";
            for (UserBankCard userBankCard : userBankCards) {
                bankInfo = "          " + userBankCard.getBankCardNo();
            }
            throw new GlobalRunTimeException("用户银行卡未完全解绑,卡号为:" + bankInfo);
        }

        // 删除用户实名制信息
        idcardInfoDao.deleteByUserId(oneByUserTel.getId());

        // 处理用户is_sm字段变为false
        userInfoDao.clearUserIsSmAndOutSideKey(oneByUserTel.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void restoreAccount(UserInfo userInfo) {
        BalanceVO balance = sandAccountHelper.getBalance(userInfo);
        if (Convert.toBigDecimal(balance.getAvailableBal()).compareTo(BigDecimal.ZERO) > 0) {
            throw new GlobalRunTimeException("当前用户衫德余额尚未清空，禁止重置");
        }
        SandBizRecord sandBizRecord = new SandBizRecord();
        sandBizRecord.setUserId(userInfo.getId());
        sandBizRecord.setCustomerOrderNo(userInfo.getSandWithdrawUuid());
        sandBizRecord.setBizMethod("restore.sand.account");
        sandBizRecord.setMethodDesc("重置衫德开户信息");
        sandBizRecord.setReqParams(userInfo.getSandWithdrawUuid());
        long snowflakeNextId = IdUtil.getSnowflakeNextId();
        userInfo.setSandWithdrawUuid(String.valueOf(snowflakeNextId));
        sandBizRecord.setResult(userInfo.getSandWithdrawUuid());
        sandBizRecord.insert();
        userInfoDao.restoreAccount(userInfo);
        sandWithdrawRecordDao.deleteByUserId(userInfo.getId());
        withdrawBankCardDao.deleteByUserId(userInfo.getId());
    }

    @Override
    public void resetOutSideKey(String userTel) {
        UserInfo userInfo = userInfoDao.getOneByUserTel(userTel);
        if (ObjectUtil.isNotNull(userInfo)) {
            Assert.isTrue(userInfoDao.updateOutSideKeyById(userInfo.getId()), () -> new GlobalRunTimeException(ErrorCode.REQUEST_FAILED_PLEASE_TRY_AGAIN_LATER));
        }
    }

    @Override
    public SelectResetOutSideKeyVO selectResetOutSideKey(String userTel) {
        UserInfo userInfo = userInfoDao.getOneByUserTel(userTel);
        SelectResetOutSideKeyVO selectResetOutSideKeyVO = new SelectResetOutSideKeyVO();
        if (ObjectUtil.isNotNull(userInfo)) {
            IdcardInfo idcardInfo = idcardInfoDao.findLastOneByUserId(userInfo.getId());
            List<UserBankCard> bankCardList = userBankCardDao.getByUserIdAndChannel(userInfo.getId(), PayChannelEnum.SAND);
            List<SandBizRecord> listByUserId = sandBizRecordDao.getListByUserId(userInfo.getId());
            selectResetOutSideKeyVO.setIdcardInfo(idcardInfo);
            selectResetOutSideKeyVO.setBankCardList(bankCardList);
            selectResetOutSideKeyVO.setListByUserId(listByUserId);
        }
        selectResetOutSideKeyVO.setUserInfo(userInfo);
        return selectResetOutSideKeyVO;
    }

    @Override
    public List<UserCollection> userIsCityMaster() {
        UserInfo user = UserPool.getUser();
        // 城主才可以创建群组.
        StaticData cityLordCollectionId = staticDataDao.getByType("city_lord_collection_id");
        Long collectionId = Convert.toLong(cityLordCollectionId.getValue());
        List<UserCollection> listByCollercitonId = userCollectionDao.getListByCollercitonId(user.getId(), collectionId);
        return listByCollercitonId;
    }

    /**
     * 根据手机号获取用户信息
     *
     * @param userTel
     * @return
     */
    @Override
    public UserInfo getByUserTel(String userTel) {
        return userInfoDao.getOneByUserTel(userTel);
    }

    @Override
    public ObtainWhetherTheUserHasACityMasterCardOrAResidentCardVO obtainWhetherTheUserHasACityMasterCardOrAResidentCard(Long id) {
        List list = Lists.newArrayList();
        list.add("resident_collection_id");
        list.add("city_lord_collection_id");
        List<StaticData> byTypes = staticDataDao.getByTypes(list);
        List<String> collect = byTypes.stream().map(StaticData::getValue).collect(Collectors.toList());
        List<Long> al = new ArrayList<>();
        for (String s : collect) {
            al.add(Convert.toLong(s));
        }
        // 根据集合数据查询用户是否有城主卡或者居民卡
        List<UserCollection> listByCollercitonId = userCollectionDao.getByCollectionIdsAndUserId(al, id);
        if (CollUtil.isNotEmpty(listByCollercitonId)) {
            return new ObtainWhetherTheUserHasACityMasterCardOrAResidentCardVO(true);
        } else {
            return new ObtainWhetherTheUserHasACityMasterCardOrAResidentCardVO(false);
        }

    }

    public String userLogin(Long id) {
        Assert.notNull(id);
//        String token = TokenUtil.createToken(id);
//        redisUtil.del(RedisKeyEnum.USER_INFO.getKey() + redisUtil.get(RedisKeyEnum.USER_INFO_RELATION.getKey() + id));
//        //存入redis
//        redisUtil.set(TokenUtil.getRedisTokenKey(token), id.toString(), 60 * 24 * 30);
//        redisUtil.set(RedisKeyEnum.USER_INFO_RELATION.getKey() + id, token, 60 * 24 * 30);
//        return token;

        StpUtil.login(id, SaLoginModel.create().setTimeout(Duration.ofDays(30).getSeconds()).build());
        return StpUtil.getTokenValue();
    }

}